R tiene muchos paquetes para resolver problemas específicos. Para usar un paquete adicional este debe instalarse y cargarse en memoria.
installed.packages()[,1] # Lista los paquetes instalados
(.packages()) # Lista los paquetes en memoriaDos recursos importantes para buscar y identificar paquetes relevantes son https://www.rdocumentation.org/ https://cran.rstudio.com/web/views/
Para instalar un paquete, por ejemplo “nycflights13”
Para cargar un paquete en memoria, se usa
En RStudio la gestión de paquetes también puede hacerse desde la interfaz del programa
En un script y para garantizar la disponibilidad de un paquete
Para acceder a la documentación de un paquete
Algunos paquetes tienen información adicional a la que se puede acceder con las funciones vignette() y demo().
A menudo es necesario leer y guardar los datos en algún formato tal que permita la importación y exportación de los mismos y su intercambio con otros programas o entornos.
Aunque puede importar y exportar archivos de muy distintos formatos, solo comentaremos como trabajar con
Para los distintos ejemplos usaremos el conjunto de datos flights del paquete nycflights13.
## tibble [336,776 x 19] (S3: tbl_df/tbl/data.frame)
## $ year : int [1:336776] 2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
## $ month : int [1:336776] 1 1 1 1 1 1 1 1 1 1 ...
## $ day : int [1:336776] 1 1 1 1 1 1 1 1 1 1 ...
## $ dep_time : int [1:336776] 517 533 542 544 554 554 555 557 557 558 ...
## $ sched_dep_time: int [1:336776] 515 529 540 545 600 558 600 600 600 600 ...
## $ dep_delay : num [1:336776] 2 4 2 -1 -6 -4 -5 -3 -3 -2 ...
## $ arr_time : int [1:336776] 830 850 923 1004 812 740 913 709 838 753 ...
## $ sched_arr_time: int [1:336776] 819 830 850 1022 837 728 854 723 846 745 ...
## $ arr_delay : num [1:336776] 11 20 33 -18 -25 12 19 -14 -8 8 ...
## $ carrier : chr [1:336776] "UA" "UA" "AA" "B6" ...
## $ flight : int [1:336776] 1545 1714 1141 725 461 1696 507 5708 79 301 ...
## $ tailnum : chr [1:336776] "N14228" "N24211" "N619AA" "N804JB" ...
## $ origin : chr [1:336776] "EWR" "LGA" "JFK" "JFK" ...
## $ dest : chr [1:336776] "IAH" "IAH" "MIA" "BQN" ...
## $ air_time : num [1:336776] 227 227 160 183 116 150 158 53 140 138 ...
## $ distance : num [1:336776] 1400 1416 1089 1576 762 ...
## $ hour : num [1:336776] 5 5 5 5 6 5 6 6 6 6 ...
## $ minute : num [1:336776] 15 29 40 45 0 58 0 0 0 0 ...
## $ time_hour : POSIXct[1:336776], format: "2013-01-01 05:00:00" "2013-01-01 05:00:00" "2013-01-01 05:00:00" ...
Partiremos de un subconjunto de flights, para ello empezamos segmentando el data.frame.
fl_ny2ws <- flights[flights$dest %in% c("IAD","BWI"),
c("origin","dest","carrier","arr_delay","air_time")]
head(fl_ny2ws)## # A tibble: 6 x 5
## origin dest carrier arr_delay air_time
## <chr> <chr> <chr> <dbl> <dbl>
## 1 LGA IAD EV -14 53
## 2 LGA BWI WN -19 40
## 3 EWR IAD EV 12 52
## 4 JFK BWI MQ 851 41
## 5 JFK IAD B6 14 52
## 6 LGA IAD EV 5 59
Para escribir un archivo de texto (delimitado) desde un data.frame se usa la función write.table o cualquiera de sus derivadas. Para leer, la función es read.table.
write.table(fl_ny2ws, file="fl_ny2ws.csv", sep=",", dec=".",
quote=TRUE, fileEncoding="UTF-8", row.names=FALSE)fl_ny2ws <- read.table("fl_ny2ws.csv", sep=",", dec=".",
quote="\"", fileEncoding="UTF-8", header=TRUE)Si se desea o dispone de un archivo delimitado por tabulaciones, el carácter tabulador se indica como \t.
Para leer y guardar datos en el formato propio de R, se usan las funciones save y load. Estas permiten almacenar y recuperar cualquier conjunto de variables del entorno de trabajo. Al recuperarlas se recuperan con el mismo nombre con el que se almacenaron.
Com se ha viso anteriormente, el data frame es el tipo de dato más usado para almacenar tablas de datos.
A menudo, para poder realizar gráficos y/o aplicar distintos procedimientos estadísticos, es necesario manipular la tabla de datos. A esto dedicaremos este apartado.
Entre las operaciones habituales que haremos sobre una tabla de datos, hay
Terminaremos este bloque introduciendo los funciones básicas del paquete dplyr que facilita la realización de algunas de estas operaciones.
Partimos de una tabla de datos sintética…
## X1.5 letters.1.5. c.rep..a...3...rep..b...2..
## 1 1 a a
## 2 2 b a
## 3 3 c a
## 4 4 d b
## 5 5 e b
## var1 var2 var3
## subject001 1 a a
## subject002 2 b a
## subject003 3 c a
## subject004 4 d b
## subject005 5 e b
df2 <- cbind(df, rnorm(5)) # añadir un vector al data frame
df2$var5 <- 5:1 # assignando valores a una nueva variable
df2## var1 var2 var3 rnorm(5) var5
## subject001 1 a a -1.48978215 5
## subject002 2 b a 0.05895738 4
## subject003 3 c a -0.74247214 3
## subject004 4 d b -0.32942373 2
## subject005 5 e b -0.78878442 1
## var1 var2 var3
## subject001 1 a a
## subject002 2 b a
## subject003 3 c a
## subject004 4 d b
## subject005 5 e b
## 1 6 e b
Existen tres formas básicas de seleccionar filas o columnas de una tablas de datos
## var1 var2 var3
## subject001 1 a a
## subject002 2 b a
## subject003 3 c a
## var1 var3
## subject001 1 a
## subject002 2 a
## subject003 3 a
## subject004 4 b
## subject005 5 b
## var1 var3
## subject001 1 a
## subject002 2 a
## subject004 4 b
## subject005 5 b
## [1] "a" "b" "c" "d" "e"
## [1] "a" "a" "a" "b" "b"
## var2 var3
## subject001 a a
## subject002 b a
## subject003 c a
## subject004 d b
## subject005 e b
## var1 var3
## subject001 1 a
## subject002 2 a
## subject004 4 b
## var1 var2 var3
## subject003 3 c a
## subject004 4 d b
## subject005 5 e b
Un mismo conjunto de datos puede representar en una tabla de datos de acuerdo con distintas oragnizaciones o formatos.
Se denomina formato ordenado, tidy, aquella organización en la que las filas representan individuos, las columnas, variables de medidas, y las intersecciones los valores de dichas medidas.
Cuando existen más de una variable que corresponde al mismo tipo de medida, entonces los datos pueden organizarse de dos formas
El formato más adecuado dependerá de los análisis y visualizaciones que quieran hacerse.
Partiremos de un subconjunto de flights…
fl_ny2ws_W <- flights[flights$dest %in% c("IAD","BWI"),
c("origin","dest","carrier","arr_delay","dep_delay")]
fl_ny2ws_W <- cbind(key = 1:nrow(fl_ny2ws_W), fl_ny2ws_W)
head(fl_ny2ws_W)## key origin dest carrier arr_delay dep_delay
## 1 1 LGA IAD EV -14 -3
## 2 2 LGA BWI WN -19 -1
## 3 3 EWR IAD EV 12 24
## 4 4 JFK BWI MQ 851 853
## 5 5 JFK IAD B6 14 15
## 6 6 LGA IAD EV 5 10
fl_ny2ws_L <- rbind(
cbind(edge = rep("origin", nrow(fl_ny2ws_W)), fl_ny2ws_W[,c(1,4)],
airport = fl_ny2ws_W[,2], delay = fl_ny2ws_W[,6]),
cbind(edge = rep("dest", nrow(fl_ny2ws_W)), fl_ny2ws_W[,c(1,4)],
airport = fl_ny2ws_W[,3], delay = fl_ny2ws_W[,5]))
colnames(fl_ny2ws_L) <- c("edge","key","carrier","airport","delay")## edge key carrier airport delay
## 1 origin 1 EV LGA -3
## 2 origin 2 WN LGA -1
## 3 origin 3 EV EWR 24
## 4 origin 4 MQ JFK 853
## 5 origin 5 B6 JFK 15
## 6 origin 6 EV LGA 10
## edge key carrier airport delay
## 14957 dest 7476 B6 IAD -4
## 14958 dest 7477 MQ BWI -9
## 14959 dest 7478 EV IAD -16
## 14960 dest 7479 EV IAD -19
## 14961 dest 7480 9E IAD -40
## 14962 dest 7481 9E BWI 2
fl_ny2ws_W2p1 <- fl_ny2ws_L[fl_ny2ws_L$edge=="origin",]
fl_ny2ws_W2p2 <- fl_ny2ws_L[fl_ny2ws_L$edge=="dest",]
fl_ny2ws_W2p1 <- fl_ny2ws_W2p1[order(fl_ny2ws_W2p1$key),-1]
fl_ny2ws_W2p2 <- fl_ny2ws_W2p2[order(fl_ny2ws_W2p2$key),-c(1,2)]
fl_ny2ws_W2 <- cbind(fl_ny2ws_W2p1,fl_ny2ws_W2p2[,-1])
colnames(fl_ny2ws_W2) <- c("key", "carrier", "origin", "dep_delay",
"dest","arr_delay")## key carrier origin dep_delay dest arr_delay
## 1 1 EV LGA -3 IAD -14
## 2 2 WN LGA -1 BWI -19
## 3 3 EV EWR 24 IAD 12
## 4 4 MQ JFK 853 BWI 851
## 5 5 B6 JFK 15 IAD 14
## 6 6 EV LGA 10 IAD 5
## key carrier origin dep_delay dest arr_delay
## 7476 7476 B6 JFK 12 IAD -4
## 7477 7477 MQ JFK -5 BWI -9
## 7478 7478 EV LGA -5 IAD -16
## 7479 7479 EV JFK -1 IAD -19
## 7480 7480 9E JFK -7 IAD -40
## 7481 7481 9E JFK 38 BWI 2
La forma más habitual de eliminar filas o columnas es segmentando la tabla de datos. Sin embargo, una columna también puede eliminarse asignando la misma a NULL.
## var1 var3
## subject001 1 a
## subject003 3 a
## subject004 4 b
## subject005 5 b
Si lo que se desea es eliminar una variable del entorno de trabajo entonces se usa la función rm.
sum_fl_ny2ws <- data.frame(edge=c("origin","dest"))
sum_fl_ny2ws$mean_delay <- apply(fl_ny2ws_W[,c("dep_delay","arr_delay")],2,
mean,na.rm=TRUE)
sum_fl_ny2ws$r_delay <- apply(fl_ny2ws_W[,c("dep_delay","arr_delay")],2,
function(x) diff(range(x,na.rm=TRUE)))
sum_fl_ny2ws$s_delay <- apply(fl_ny2ws_W[,c("dep_delay","arr_delay")],2,
sd,na.rm=TRUE)
sum_fl_ny2ws## edge mean_delay r_delay s_delay
## 1 origin 16.84267 885 47.85548
## 2 dest 13.11556 904 51.52259
sum_fl_ny2ws <- data.frame(edge=c("origin","dest"))
sum_fl_ny2ws$mean_delay <- by(fl_ny2ws_L$delay,fl_ny2ws_L$edge,
mean,na.rm=TRUE)
sum_fl_ny2ws$r_delay <- by(fl_ny2ws_L$delay,fl_ny2ws_L$edge,
function(x) diff(range(x,na.rm=TRUE)))
sum_fl_ny2ws$s_delay <- by(fl_ny2ws_L$delay,fl_ny2ws_L$edge,sd,na.rm=TRUE)
sum_fl_ny2ws## edge mean_delay r_delay s_delay
## 1 origin 13.11556 904 51.52259
## 2 dest 16.84267 885 47.85548
dplyrEstas mismas operaciones que se han comentado más arriba, se pueden llevar a cabo también a partir de un sistema coherente de métodos creado como una gramática para la manipulación de datos, el paquete dplyr –que forma parte de tidyverse–.
En dplyr las operaciones básicas, se realizan mediante cuatro métodos:
select: segmentar columnas,filter: segmentar filas,mutate: crear nuevas columnas, yarrange: ordenar.Estas se encadenan usando el operador pipe, %>%.
df <- flights %>% dplyr::select(origin, dest, arr_delay) %>%
filter(origin == "LGA" & (dest == "IAD" | dest == "BWI")) %>%
mutate(arr_delay_h=arr_delay/60) %>%
arrange(-arr_delay_h)
df## # A tibble: 1,818 x 4
## origin dest arr_delay arr_delay_h
## <chr> <chr> <dbl> <dbl>
## 1 LGA IAD 398 6.63
## 2 LGA IAD 326 5.43
## 3 LGA IAD 312 5.2
## 4 LGA IAD 306 5.1
## 5 LGA IAD 292 4.87
## 6 LGA IAD 281 4.68
## 7 LGA IAD 280 4.67
## 8 LGA IAD 265 4.42
## 9 LGA IAD 262 4.37
## 10 LGA IAD 253 4.22
## # ... with 1,808 more rows
Para la creación de resúmenes a partir de tablas en formato largo, es muy útil y cómoda la combinación group_by y summarize.
## # A tibble: 2 x 2
## dest mean_delay
## <chr> <dbl>
## 1 BWI -7.87
## 2 IAD 13.7
Por último, las conversiones entre formatos también pueden hacerse a partir de las funciones spread y gather del paquete tidyr –incluido en tidyverse y que se integra de forma natural en la gramática propuestas por dplyr–.
La gramática de gráficos es una aproximación teórica al estudio de los componentes de un gráfico. De acuerdo con este análisis, un gráfico se puede construir mediante la especificación de un conjunto de capas y componentes que definen los datos, la asociación de los mismos a aspectos del gráfico, la especificación de la relación entre los valores de las variables de los datos con las del gráfico, la estructura geométrica del gráfico…
Wilkinson, L. (2006). The grammar of graphics. Springer Science & Business Media.
ggplot2ggplot2 es un paquete de R que implementa de la gramática de gráficos.
Wickham, H. (2010). A layered grammar of graphics. Journal of Computational and Graphical Statistics, 19(1), 3-28.
Referencias:
ggplot2 forma parte del paquete tidyverse (aunque también puede instalarse y cargarse autónomamente).
ggplot2 – capas y elementos del gráficoEn ggplot2 cada elemento gráfico que representa un conjunto de datos constituye una capa. Una o más capas constituyen un gráfico.
Cada capa queda definida mediante la especificación de sus elementos. Los principales son
En ggplot2, los gráficos constituyen un objeto de R y se construyen de forma aditiva.
Por ejemplo,
ggplot2 – datosEn ggplot2, el elemento data (datos) se introduce como primer argumento de la función ggplot. Debe corresponder a una tabla de datos o un tipo de datos convertible a tabla de datos.
ggplot2 – mapeado estéticoEl mapping (mapeado estético) corresponde al establecimiento de relaciones entre variables de los datos y variables del gráfico. Es el segundo argumento de la función ggploty debe crearse con al función de apoyo aes.
Para variables cuantitativas, los mapeados más comunes corresponden a
x, y…sizecolor, fillPara variable cualitativas, los mapeados más frecuentes son
x, y…color, fillshapeggplot2 – geometríasLas geometrías (geom_) indican la forma que debe tener el gráfico, es decir, cómo se articulan las variables del gráfico. Se añaden al gráfico sumándose al objeto creado por ggplot.
Son geometrías de uso común
geom_pointgeom_line, geom_vline, geom_hlinegeom_bargeom_histogramgeom_boxplotUn resumen de las geometrías y su relación con las variables del gráfico que reconoce cada una de ellas figura en https://github.com/rstudio/cheatsheets/raw/master/data-visualization-2.1.pdf.
ggplot2Veremos cómo crear en ggplot2 los gráficos más habituales, añadiendo algunas consideraciones para aquellos casos donde los gráficos realizados con base tienen prestaciones insuficientes.
De forma general, los gráficos en ggplot2 se construyen a partir de tablas de datos (data frames), de los cuales se seleccionan las variables a representar.
Usaremos 1000 datos del conjunto de datos diamonds para crear los distintos ejemplos.
## tibble [1,000 x 10] (S3: tbl_df/tbl/data.frame)
## $ carat : num [1:1000] 1.12 1.24 0.31 1.5 0.32 0.31 0.33 0.72 0.32 1 ...
## $ cut : Ord.factor w/ 5 levels "Fair"<"Good"<..: 5 5 4 4 4 2 5 4 5 5 ...
## $ color : Ord.factor w/ 7 levels "D"<"E"<"F"<"G"<..: 4 6 2 1 6 2 4 2 4 2 ...
## $ clarity: Ord.factor w/ 8 levels "I1"<"SI2"<"SI1"<..: 4 3 4 2 4 3 8 7 8 3 ...
## $ depth : num [1:1000] 62.2 62 61 58.7 62.6 63.3 61.7 62.9 61.8 61.9 ...
## $ table : num [1:1000] 54 58 59 57 58 55 58 59 55 56 ...
## $ price : int [1:1000] 7193 6232 872 9173 449 544 968 3566 1020 5458 ...
## $ x : num [1:1000] 6.65 6.83 4.39 7.48 4.37 4.31 4.42 5.75 4.43 6.37 ...
## $ y : num [1:1000] 6.7 6.88 4.33 7.42 4.42 4.35 4.46 5.67 4.41 6.45 ...
## $ z : num [1:1000] 4.15 4.25 2.66 4.37 2.75 2.74 2.74 3.59 2.73 3.97 ...
ggplot2 – gráfico de dispersiónAñadiendo una tercera variable (cut) y modificando algunos aspectos de formato…
Añadiendo líneas de tendencia…
## `geom_smooth()` using formula 'y ~ x'
ggplot2 – histogramaY en función del corte…
En frecuencias relativas (por grupo)…
Quizás funcione mejor un gráfico de densidades…
ggplot2 – diagrama de barrasEn función de la claridad…
Para comparar entre frecuencias absolutas, funcionan mejor las barras separadas.
Para comparar entre frecuencias relativas acumuladas, son mejores las barras apiladas en frecuencia relativa (para cada clase).
Los diagramas de barras también pueden crearse a partir de tablas de datos agrupados. En este caso, debe indicarse qué variable es la y e incluir stat="identity" en el geom_bar.
ggplot2 – diagrama de cajaNOTA: Para el geom_boxplot se requieren dos variables. Si no hay variable independiente se puede incluir x=1.
Y en función del corte…
El gráfico se puede mejorar mostrando todos los puntos, con una posición aleatorizada.
O incluyendo un violin plot y un punto para la media…
ggplot2 – elementos adicionalesAdemás de los elementos ya presentados (datos, mapeado estético y geometrías), otros elementos de ggplot2 permiten controlar aspectos adicionales del gráfico, por ejemplo
scale_...: controlan los aspectos relativos a la presentación de las variables del gráfico,coord_...: establecen el sistema de coordenadas usado en la geometría,labs: establece los títulos del gráfico,theme, theme_...: controlan la part del gráfico que no corresponde a datos (non-data ink), yfacet_: permite la creació de secuencia de gráficos en función de una o dos variablesUn ejemplo para terminar…
ggplot(diaM, aes(x=carat, y = price, shape = cut, col = clarity)) +
geom_point(alpha=.6) +
scale_x_continuous(breaks=1:3) +
scale_y_continuous(trans="log10") +
scale_color_brewer(palette="Spectral")+
facet_grid(cut ~ clarity) +
theme_bw() +
theme(legend.position = "none",text = element_text(size=10))## Warning: Using shapes for an ordinal variable is not advised